﻿#!/usr/bin/env python
# Download sms messages and archive them if present in inbox
#
# NOTE: Set download_type below:
# 'inbox': Download SMS messages in inbox only and archive them
# 'sms': Download all SMS messages and archive them. Set this for initial run
download_type = 'inbox'
#download_type = 'sms'
# Download directory for SMS messages
outputDir = 'downloadedsms'
from googlevoice import Voice
import re
import sys
import json
import time
import os
import os.path
import glob
import csv
def getNames(html):
    import BeautifulSoup
    Names = {}
    tree = BeautifulSoup.BeautifulSoup(html)
    convBlock = tree.findAll('div', attrs={'id' : True}, recursive=False)
    for conv in convBlock:
        fromnames = []
        rows = conv.findAll(attrs={'class' : 'gc-message-sms-from'})
        for row in rows:
            fromname = ' '.join(row.findAll(text=True)).strip().replace(':','')
            fromnames.append(fromname)
        if fromnames:
            Names[conv['id']] = fromnames
    return Names
def ensureDirectory(path):
    if not os.path.isdir(path):
        try:
            os.makedirs(path)
        except OSError, e:
            if e.errno != errno.EEXIST:
                raise
jsondir = outputDir + '/json'
csvdir = outputDir + '/csv'
ensureDirectory(jsondir)
ensureDirectory(csvdir)
voice = Voice()
voice.login()
conversations = []
page = 0
while True:
    page += 1
    getattr(voice,download_type)(terms={ 'page':('p%d' % page) })
    value = getattr(voice,download_type)
    jsonData = value.data
    pagenames = getNames(value.html)
    pageconversations = []
    if 'messages' not in jsonData or len(jsonData['messages']) < 1:
        break
    for message in jsonData['messages']:
        if 'sms' not in jsonData['messages'][message]['labels']:
            continue 
        getattr(voice,'message')(terms={ 'messageId':jsonData['messages'][message]['id'] })
        pageconversations.append(getattr(voice,'message').data['messages'])
    for i in pageconversations:
        for j in i:
            if 'children' not in i[j]:
                continue
            if j not in pagenames:
                continue
            c = 0
            maxc = len(pagenames[j])
            for conversation in i[j]['children']:
                if c == maxc:
                    break
                if not conversation['fromName']:
                    if pagenames[j][c]:
                        conversation['fromName'] = pagenames[j][c]
                c += 1
    conversations += pageconversations
    print 'page %d' % page
for conv in conversations:
    for key in conv:
        head = '/' + conv[key]['phoneNumber'].replace('+','') + '.'
        timestamp = time.strftime('%Y%m%d.%H%M%S',time.localtime(int(conv[key]['startTime'])/1000))
        tail = '.' + key
        jsonname = jsondir + head + timestamp + tail + '.json'
        csvname = csvdir + head + timestamp + tail + '.csv'
        for oldfile in glob.glob(jsondir + head + '*' + tail + '.json'):
            if oldfile != jsonname:
                os.unlink(oldfile)
        for oldfile in glob.glob(csvdir + head + '*' + tail + '.csv'):
            if oldfile != csvname:
                os.unlink(oldfile)
        f = open(jsonname,'wb')
        f.write(json.dumps(conv,sort_keys=True, indent=4))
        f.close()
        f = csv.writer(open(csvname,'wb'))
        for i in conv[key]['children']:
            f.writerow([i['fromName'].encode('utf-8'),i['displayStartDateTime'].encode('utf-8'),i['message'].encode('utf-8')])
        if 'inbox' in conv[key]['labels']:
            voice.archive(key)
print len(conversations), 'conversations written to directory', outputDir
print 'Any conversations in inbox are now archived'
